#ifndef __TOYM__NET__TCP_SERVER_H__
#define __TOYM__NET__TCP_SERVER_H__

#include "net/Acceptor.h"
#include "net/Socket.h"
#include "net/InetAddress.h"
#include "Base/noncopyable.h"
#include <string>
#include <unordered_map>
#include <atomic>
#include <memory>

namespace toym
{
namespace net
{

class EventLoop;
class EventLoopThreadPool;

class TcpServer: noncopyable {
public:
    TcpServer(EventLoop* loop, const InetAddress& addr, const std::string& name = "TcpServer");
    ~TcpServer();
    std::string& getServerName() {
        return m_serverName;
    }
    const std::string& getServerName() const {
        return m_serverName;
    }

    void setThreadNum(int nThread);

    void start();

    void setConnectionCallback(const ConnectionCallback_t& cb) {
        m_connectionCb = cb;
    }
    void setConnectionCallback(ConnectionCallback_t&& cb) {
        m_connectionCb = std::move(cb);
    }

    void setMessageCallback(const MessageCallback_t& cb) {
        m_messageCb = cb;
    }
    void setMessageCallback(MessageCallback_t&& cb) {
        m_messageCb = std::move(cb);
    }

    void removeConnection(const TcpConnectionPtr& conn);

private:

    void removeConnectionInThread(const TcpConnectionPtr& conn);

    void handleNewConnection(Socket sock, const InetAddress& peerAddr);

    static
    void defaultConnectionCb(const TcpConnectionPtr& conn);

    static
    void defaultMessageCb(const TcpConnectionPtr& conn, Buffer* buf, Timestamp ts);

    EventLoop* m_loop;
    std::string m_serverName;
    Acceptor m_acceptor;
    ConnectionCallback_t m_connectionCb;
    MessageCallback_t m_messageCb;
    std::unordered_map<std::string, TcpConnectionPtr> m_conns;
    std::unique_ptr<EventLoopThreadPool> m_threadPool;

    static std::atomic_int64_t s_connSeq;
};

} // namespace net

} // namespace toym


#endif //__TOYM__NET__TCP_SERVER_H__